﻿using System;
using System.Collections.Generic;
using System.Linq;
using FastTravel.DataAccess.Base;
using FastTravel.DataAccess.Interface;
using FastTravel.DB;
using FastTravel.DB.DTO;
using StructureMap;

namespace FastTravel.BusinessLogic
{
	/// <summary>
	/// Класс управления отелями
	/// </summary>
	public class HotelManager
	{
		/// <summary>
		/// Хранилище отелей
		/// </summary>
		private static IRepository<Hotel> HotelRepository
		{
			get { return ObjectFactory.GetInstance<IRepository<Hotel>>(); }
		}

		/// <summary>
		/// Хранилище курортов
		/// </summary>
		private static IRepository<Resort> ResortRepository
		{
			get { return ObjectFactory.GetInstance<IRepository<Resort>>(); }
		}

		/// <summary>
		/// Создать отель
		/// </summary>
		/// <param name="name">Название отеля</param>
		/// <param name="description">Описание</param>
		/// <param name="buildYear">Год постройки</param>
		/// <param name="floorCount">Число этажей</param>
		/// <param name="roomsCount">Число комнат</param>
		/// <param name="resortId">ID курорта</param>
		/// <param name="starLevel">Звездность</param>
		/// <returns>Отель</returns>
		public static Hotel Add(string name, string description, int buildYear, int floorCount, int roomsCount, int resortId, int starLevel)
		{
			if (!string.IsNullOrWhiteSpace(name))
			{
				Resort resort = ResortManager.Get(resortId);

				Hotel hotel = new Hotel
				              	{
				              		Name = name,
				              		AddedDate = DateTime.Now,
				              		Description = description,
				              		BuildYear = buildYear,
				              		FloorCount = floorCount,
				              		IsArchive = false,
				              		Resort = resort,
				              		RoomsCount = roomsCount,
				              		StarLevel = starLevel,
				              		RoomsCategory = ""
				              	};

				HotelRepository.Add(hotel);
				return hotel;
			}
			return null;
		}


		/// <summary>
		/// Получить отель
		/// </summary>
		/// <param name="id">ID отеля</param>
		/// <returns>Отель</returns>
		public static Hotel Get(int id)
		{
			return HotelRepository.Single(x => x.ID == id);
		}

		/// <summary>
		///  Получить страницу отелей
		/// </summary>
		/// <param name="start">Начальная страница</param>
		/// <param name="limit">Размер страницы</param>
		/// <param name="sort">Сортировка по полю</param>
		/// <param name="dir">Направление сортировки</param>
		/// <param name="count">Общее число отелей</param>
		/// <returns>Список отелей</returns>
		public static List<Hotel> GetPage(int start, int limit, string sort, string dir, out int count)
		{
			return HotelRepository.GetPage(start, limit, sort, dir, out count);
		}

		/// <summary>
		/// Получить страницу отелей
		/// </summary>
		/// <param name="start">Начальная страница</param>
		/// <param name="limit">Размер страницы</param>
		/// <param name="sort">Сортировка по полю</param>
		/// <param name="dir">Направление сортировки</param>
		/// <param name="filterByName">Фильтр по названию отеля</param>
		/// <param name="starLevel">Фильтр по количеству звезд</param>
		/// <param name="countryId">Фильтр по стране</param>
		/// <param name="resortId">Фильтр по курорту</param>
		/// <param name="totalCount">Общее число отелей</param>
		/// <returns>Списо</returns>
		public static List<HotelDTO> GetPageDTO(int start, int limit, string sort, string dir, 
			string filterByName, int starLevel, int countryId, int resortId, out int totalCount)
		{

			var query = HotelRepository.GetQuery().Select(e => e);

			// фильтр по названию отеля
			if (!string.IsNullOrEmpty(filterByName))
			{
				query = query.Where(x => x.Name.ToLower().StartsWith(filterByName.ToLower()));
			}

			// фильтр по количеству звезд
			if (starLevel != -1)
			{
				query = query.Where(x => x.StarLevel == starLevel);
			}

			// фильтр по стране
			if (countryId != -1)
			{
				query = query.Where(x => x.Resort.Country.ID == countryId);
			}

			// фильтр по курорту
			if (resortId != -1)
			{
				query = query.Where(x => x.Resort.ID == resortId);
			}

			totalCount = query.Count();

			if (!string.IsNullOrEmpty(sort))
			{
				query = dir == "ASC"
							? HotelRepository.SortByQuery<Hotel>(query, sort, true)
							: HotelRepository.SortByQuery<Hotel>(query, sort, false);
			}

			if (start >= 0 && limit > 0)
			{
				query = query.Skip(start).Take(limit);
			}

			List<HotelDTO> result = query.Select(item => new HotelDTO
			                                              	{
			                                              		ID = item.ID,
			                                              		CountryName = item.Resort.Country.Name,
			                                              		Description = item.Description,
			                                              		CountryID = item.Resort.Country.ID,
			                                              		Name = item.Name,
			                                              		ResortID = item.Resort.ID,
			                                              		ResortName = item.Resort.Name,
			                                              		StarDescription = "",
			                                              		StarLevel = item.StarLevel
			                                              	}).ToList();

			return result.ToList();
		}

		/// <summary>
		/// Получить все отели
		/// </summary>
		/// <returns>Список отелей</returns>
		public static IEnumerable<Hotel> GetAll()
		{
			return HotelRepository.GetAll();
		}

		/// <summary>
		/// Получить общее количество отелей
		/// </summary>
		/// <returns>Количество отелей</returns>
		public static int Count()
		{
			return HotelRepository.GetQuery().Count();
		}

		/// <summary>
		/// Удалить отель
		/// </summary>
		/// <param name="id">ID</param>
		public static void Delete(int id)
		{
			Hotel hotel = HotelRepository.Single(x => x.ID == id);
			if (hotel != null)
			{
				HotelRepository.Delete(hotel);
			}
		}

		/// <summary>
		/// Обновить данные об отеле
		/// </summary>
		/// <param name="hotelId">ID отеля</param>
		/// <param name="name">Название отеля</param>
		/// <param name="description">Описание отеля</param>
		/// <param name="buildYear">Год постройки</param>
		/// <param name="floorCount">Число этажей</param>
		/// <param name="roomsCount">Число комнат</param>
		/// <param name="resortId">ID курорта</param>
		/// <param name="starLevel">Звездность</param>
		public static void Update(int hotelId, string name, string description, int buildYear, int floorCount, int roomsCount, int resortId, int starLevel)
		{
			Hotel hotel = HotelRepository.Single(x => x.ID == hotelId);
			Resort resort = ResortRepository.Single(x => x.ID == resortId);
			if (hotel != null)
			{
				hotel.Name = name;
				hotel.Description = description;
				hotel.BuildYear = buildYear;
				hotel.FloorCount = floorCount;
				hotel.RoomsCount = roomsCount;
				hotel.Resort = resort;
				hotel.StarLevel = starLevel;
				
				HotelRepository.SaveChanges();
			}
		}

	
	}
}
